﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Data;
using System.Data.SqlClient;
using BEELab.Data;

namespace BEELab
{
    public partial class EditStage : System.Web.UI.Page
    {
        public string stageID;
        protected Dictionary<int, String> stagesDescriptions;

        /// <summary>
        /// Empty C'tor
        /// </summary>
        public EditStage()
        {

        }

        /// <summary>
        /// Presents all descriptions of functions that are public or related to user.
        /// </summary>
        private void LoadFunctionDescriptions()
        {
            SqlCommand command = new SqlCommand();
            command.CommandText = "SELECT ID, Description FROM Programs WHERE (OwnerID=@OwnerID OR Permission='Public') AND Type='Function' AND isVisible='true';";
            command.Parameters.Add(new SqlParameter("@OwnerID", int.Parse(Session["UserID"].ToString())));
            DataTable dt = DBHelper.ExecuteQuery(command);

            DescriptionsLiteral.Text = "var functionDescriptions = new Array();";

            foreach (DataRow row in dt.Rows)
            {
                DescriptionsLiteral.Text += "functionDescriptions[" + row[0] + "] = \"" + row[1].ToString().Replace("\"", "\\\"") + "\";";
            }

            if (dt.Rows.Count > 0)
            {
                string first = dt.Rows[0][0].ToString();
                DescriptionsLiteral.Text += "$('#ContentBody_txtFuncDesc').text(functionDescriptions[" + first + "]);";
            }
        }

        /// <summary>
        /// Validates all stages names correction
        /// </summary>
        private void SetStageNameValidation()
        {
            string Names = BEELab.Logic.ProgramManagement.StageManagement.StageManagement.EnumerateStages(int.Parse(Request.QueryString["ID"].ToString()), "|");
            if (Names.Length > 0)
            {
                StageRegularExpressionValidator.ValidationExpression = "^(?!" + Names + ").*$";
            }
            else
            {
                StageRegularExpressionValidator.ValidationExpression = ".*";
            }
        }

        /// <summary>
        /// Validates all variables names correction
        /// </summary>
        private void SetVarNamesValidation()
        {
            string varNames = BEELab.Logic.ProgramManagement.VariableManagement.VariableManagement.EnumerateVariablesForProgram(BEELab.Logic.ProgramManagement.StageManagement.StageManagement.GetProgramID(int.Parse(Request.QueryString["ID"].ToString())), "|");
            if (varNames.Length > 0)
            {
                RegexValidator2.ValidationExpression = "^(?!" + varNames + ").*$";
            }
            else
            {
                RegexValidator2.ValidationExpression = ".*";
            }
        }

        /// <summary>
        /// Validates all containers names of a stage correction
        /// </summary>
        private void SetInstanceNameValidation()
        {
            string Names = BEELab.Logic.ProgramManagement.StageManagement.ContainerManagement.EnumerateContainersForStage(int.Parse(Request.QueryString["ID"].ToString()), "|");
            if (Names.Length > 0)
            {
                InstanceRegexValidator.ValidationExpression = "^(?!" + Names + ").*$";
            }
            else
            {
                InstanceRegexValidator.ValidationExpression = ".*";
            }
        }

        /// <summary>
        ///  Validates the correction of all blocks names belongs to this stage
        /// </summary>
        private void SetBlockNamesValidation()
        {
            string blockNames = BEELab.Logic.ProgramManagement.StageManagement.BlockElements.EnumerateBlocksForStage(int.Parse(Request.QueryString["ID"].ToString()), "|");
            if (blockNames.Length > 0)
            {
                RegularExpressionValidator3.ValidationExpression = "^(?!" + blockNames + ").*$";
                BlocksEnumerationLiteral.Text = "var BlocksRE = /" + "^(?!\\.$|" + blockNames + ").*$/";
            }
            else
            {
                RegularExpressionValidator3.ValidationExpression = ".*";
                BlocksEnumerationLiteral.Text = "var BlocksRE = /.*/";
            }
        }

        /// <summary>
        /// Validates all data labels names of a stage correction
        /// </summary>
        private void SetDataLabelsValidation()
        {
            string labels = BEELab.Logic.ProgramManagement.StageManagement.DataElements.EnumerateDataElementsForStage(int.Parse(Request.QueryString["ID"].ToString()), "|");
            if (labels.Length > 0)
            {
                RegexDataLabel.ValidationExpression = "^(?!" + labels + ").*$";
            }
            else
            {
                RegexDataLabel.ValidationExpression = ".*";
            }
        }

        /// <summary>
        /// Selects all blocks of a stage that need to be invisible from DB,
        /// and hide them all on GUI
        /// </summary>
        private void HideElements()
        {
            SqlCommand command = new SqlCommand();
            command.CommandText = "SELECT ID FROM BlockElements WHERE StageID=@StageID AND isVisible='False'";
            command.Parameters.Add(new SqlParameter("@StageID", int.Parse(Request.QueryString["ID"])));
            DataTable dt = DBHelper.ExecuteQuery(command);

            HideElementsLiteral.Text = "";
            foreach (DataRow row in dt.Rows)
            {
                HideElementsLiteral.Text += "$(\"ol\").find(\"[data-id='list_" + row[0].ToString() + "']\").find(\".show\")[0].click();";
            }
        }

        /// <summary>
        /// Occures on every page load (first time or Post Back)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Page_Load(object sender, EventArgs e)
        {
            if (Session["UserID"] != null)
            {
                SqlCommand command2 = new SqlCommand();
                command2.CommandText = "SELECT ID, Name, Description FROM Programs WHERE (OwnerID=@UserID OR Permission='Public') AND Type='Function' AND isVisible='true'";
                command2.Parameters.Add(new SqlParameter("@UserID", Session["UserID"]));
                DataTable dt2 = DBHelper.ExecuteQuery(command2);
                stagesDescriptions = new Dictionary<int, string>();
                foreach (DataRow row in dt2.Rows)
                {
                    stagesDescriptions.Add(Convert.ToInt32(row["ID"]), row["Description"].ToString());
                }
            }

            if (Request.QueryString["ID"] != null && Session["UserID"] != null && BEELab.Logic.ProgramManagement.StageManagement.StageManagement.GetOwnerID(int.Parse(Request.QueryString["ID"].ToString())) != int.Parse(Session["UserID"].ToString()) && (Session["Admin"] == null || (bool)Session["Admin"] == false))
            {
                Response.Redirect("Main.aspx");
            }

            SqlCommand command;
            DataTable dt;

            if (Request.QueryString["ID"] != null)
            {
                HideElements();

                LoadFunctionDescriptions();

                DocumentReadyLiteral.Text = "";
            }


            if (!IsPostBack)
            {
                if (Request.QueryString["ID"] != null)
                {
                    SetVarNamesValidation();

                    SetBlockNamesValidation();

                    SetDataLabelsValidation();

                    SetInstanceNameValidation();

                    SetStageNameValidation();

                    string Type = BEELab.Logic.ProgramManagement.ExperimentManagement.GetType(BEELab.Logic.ProgramManagement.StageManagement.StageManagement.GetProgramID(int.Parse(Request.QueryString["ID"].ToString())));
                    
                    if (Type.Equals("Experiment"))
                    {
                        DivVariables.Style.Add("display", "none");
                        PresentationLayertxtContent.Text = BEELab.Logic.ProgramManagement.StageManagement.PresentationElements.GetContent(BEELab.Logic.ProgramManagement.StageManagement.PresentationElements.GetIDByName(int.Parse(Request.QueryString["ID"].ToString()), Properties.Settings.Default.PresentationLayer + int.Parse(Request.QueryString["ID"].ToString())));

                        command = new SqlCommand();
                        command.CommandText = "SELECT Name FROM Variables WHERE ProgramID=(SELECT ProgramID FROM Stages WHERE ID=@StageID)";
                        command.Parameters.Add(new SqlParameter("@StageID", int.Parse(Request.QueryString["ID"].ToString())));
                        dt = BEELab.Data.DBHelper.ExecuteQuery(command);

                        FillVariablesMenu(dt);

                        command = new SqlCommand();
                        command.CommandText = "SELECT Name FROM PresentationElements WHERE StageID=@StageID AND Name!=@PresentationLayer";
                        command.Parameters.Add(new SqlParameter("@StageID", int.Parse(Request.QueryString["ID"].ToString())));
                        command.Parameters.Add(new SqlParameter("@PresentationLayer", Properties.Settings.Default.PresentationLayer + int.Parse(Request.QueryString["ID"].ToString())));
                        dt = BEELab.Data.DBHelper.ExecuteQuery(command);

                        FillPresentationElementsMenu(dt);
                    }
                    else
                    {
                        string Name = BEELab.Logic.ProgramManagement.StageManagement.StageManagement.GetName(int.Parse(Request.QueryString["ID"].ToString()));
                        DivStageInfo.Style.Add("display", "none");
                        DivDataLayer.Style.Add("display", "none");

                        if (Name.Equals("Settings"))
                        {
                            DivPresentationElements.Style.Add("display", "none");
                            DivVariables.Style.Add("display", "none");
                            PresentationLayertxtContent.Text = BEELab.Logic.ProgramManagement.StageManagement.PresentationElements.GetContent(BEELab.Logic.ProgramManagement.StageManagement.PresentationElements.GetIDByName(int.Parse(Request.QueryString["ID"].ToString()), Properties.Settings.Default.PresentationLayer + int.Parse(Request.QueryString["ID"].ToString())));
                        }
                        else
                        {
                            DivPresentationLayer.Style.Add("display", "none");
                        }
                    }

                    txtName.Text = BEELab.Logic.ProgramManagement.StageManagement.StageManagement.GetName(int.Parse(Request.QueryString["ID"].ToString()));
                    txtDescription.Text = BEELab.Logic.ProgramManagement.StageManagement.StageManagement.GetDescription(int.Parse(Request.QueryString["ID"].ToString()));
  
                }
            }

            if (Request.QueryString["ID"] != null && Request.QueryString["ID"].ToString().Equals("") == false)
            {
                FillLogicLayer();

                PopulateBlocksLiteral();
            }
        }

        string SelectedCallText;
        /// <summary>
        /// Gets all blocks that related to the stage from DB, and binding it to GUI.
        /// </summary>
        private void PopulateBlocksLiteral()
        {
            //If a target block has been selected to this call - save its value on NewCallContent
            if (NewCallContent.SelectedItem != null)
            {
                SelectedCallText = NewCallContent.SelectedItem.Text;
            }
            else
            {
                SelectedCallText = "";
            }
            NewCallContent.DataBind();


            BlocksLiteral.Text = "";
            SqlCommand command = new SqlCommand();
            command.CommandText = "SELECT Name FROM BlockElements WHERE StageID=@StageID AND Type='Block'";
            command.Parameters.Add(new SqlParameter("StageID", Request.QueryString["ID"].ToString()));
            DataTable dt = BEELab.Data.DBHelper.ExecuteQuery(command);

            if (dt != null)
            {
                foreach (DataRow row in dt.Rows)
                {
                    BlocksLiteral.Text += '\'' + row["Name"].ToString() + "', ";
                }
            }
        }

        /// <summary>
        /// Gets a DataTable containing all variables names that related to current experiment,
        /// and binding it to GUI.
        /// </summary>
        /// <param name="dt">DataTable of all variables names related to current experiment</param>
        private void FillVariablesMenu(DataTable dt)
        {
            if (dt == null)
                return;

            VariablesLiteral.Text = "";

            foreach (DataRow row in dt.Rows)
            {
                VariablesLiteral.Text += "{text: '" + row["Name"].ToString() + "', onclick: function() {editor.insertContent('" + Properties.Settings.Default.VariablePrefix + row["Name"].ToString() + Properties.Settings.Default.VariableSuffix + "');}},";
            }

            if (Request.QueryString["ID"] != null)
            {
                //VariablesLiteral.Text += "{text: 'Create New Variable', onclick: function() { editor.windowManager.open({ scrollbars: 'false', title: \"Create New Variable\", url: \"EditVariable.aspx?InTinyMCE=true&ProgramID=" + BEELab.Logic.ProgramManagement.StageManagement.PresentationElements.GetProgramID(int.Parse(Request.QueryString["ID"].ToString())) + "\", width: 700, height: 450 }); }}";
            }
            else if (Request.QueryString["StageID"] != null)
            {
                //VariablesLiteral.Text += "{text: 'Create New Variable', onclick: function() { editor.windowManager.open({ scrollbars: 'false', title: \"Create New Variable\", url: \"EditVariable.aspx?InTinyMCE=true&ProgramID=" + BEELab.Logic.ProgramManagement.StageManagement.StageManagement.GetProgramID(int.Parse(Request.QueryString["StageID"].ToString())) + "\", width: 700, height: 450 }); }}";
            }
        }

        /// <summary>
        /// Gets a DataTable containing all Presentation Elements names that related to current experiment,
        /// and binding it to GUI.
        /// </summary>
        /// <param name="dt">DataTable of all Presentation Elements names related to current experiment</param>
        private void FillPresentationElementsMenu(DataTable dt)
        {
            if (dt == null)
                return;

            PresentationLiteral.Text = "";

            foreach (DataRow row in dt.Rows)
            {
                PresentationLiteral.Text += "{text: '" + row["Name"].ToString() + "', onclick: function() {editor.insertContent('" + Properties.Settings.Default.PresentationPrefix + row["Name"].ToString() + Properties.Settings.Default.PresentationSuffix + "');}},";
            }
        }

        /// <summary>
        /// Retrieves all block elements that related to current experiment,
        /// and binding it to GUI.
        /// </summary>
        public void FillLogicLayer()
        {
            SqlCommand command = new SqlCommand();
            command.CommandText = "SELECT * FROM BlockElements WHERE StageID=@StageID AND ParentID=0 ORDER BY Place";
            command.Parameters.Add(new SqlParameter("@StageID", int.Parse(Request.QueryString["ID"].ToString())));
            DataTable dt = BEELab.Data.DBHelper.ExecuteQuery(command);

            rptLogicLayer.DataSource = dt;
            rptLogicLayer.DataBind();
        }

        protected void rptLogicLayer_ItemDataBound(object sender, RepeaterItemEventArgs e)
        {
            if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
            {
                var hfDataType = (HiddenField)e.Item.FindControl("hfDataType");
                var hfCCID = (HiddenField)e.Item.FindControl("hfCCID");
                var ltlBlockName = (Literal)e.Item.FindControl("ltlBlockName");
                var tName = (HtmlInputText)e.Item.FindControl("tName");
                var ltlDataType = (Literal)e.Item.FindControl("ltlDataType");
                var ltlDescription = (Literal)e.Item.FindControl("ltlDescription");
                var tDesc = (HtmlInputText)e.Item.FindControl("tDesc");
                var ltlUnassigned = (Literal)e.Item.FindControl("ltlUnassigned");
                var ltlNested = (Literal)e.Item.FindControl("ltlNested");
                var ltlExtraDesc = (Literal)e.Item.FindControl("ltlExtraDesc");
                var item = (DataRowView)e.Item.DataItem;
                var list_item = (HtmlControl)e.Item.FindControl("list_item");
                var exDesc = @"<div class='loglogic clearfix inplace-edit'><p>{4}</p><div class='ico-texthold'>
				                <a href='#' class='icoedit' data-id='{1}' data-type='{2}'>edit</a></div></div>
                                <div class='loglogic clearfix inplace-cntr'><p><textarea class='in-textarea'>{0}</textarea>
                                </p><div class='ico-texthold'><input type='submit' class='icosave' data-id='{1}' value='Save' data-type='{2}' data-cmpnttype='{3}' data-updateType='e' />
                                <a class='in-cancel' href='#'>Cancel</a></div></div>";
                var hblock = (HtmlControl)e.Item.FindControl("hblock");
                var drg = (HtmlControl)e.Item.FindControl("drg");
                var del = (HtmlControl)e.Item.FindControl("del");
                var edt = (PlaceHolder)e.Item.FindControl("edt");
                var edt2 = (PlaceHolder)e.Item.FindControl("edt2");
                var logicblock = (HtmlControl)e.Item.FindControl("logicblock");

                list_item.Attributes.Add("data-id", "list_" + item["ID"].ToString());

                //if (!bool.Parse(item["isVisible"].ToString()))
                //{
                 //   ((HtmlControl)e.Item.FindControl("show")).Attributes["class"] = "hide";
                //}

                // default blocks
                var pblocks = new[] { "onload", "onpost", "onmessage", "beforeload", "afterpost" };

                if (item["Type"].ToString() == "Block")
                {
                    hfCCID.Value = item["ID"].ToString();
                    tName.Value = ltlBlockName.Text = item["Name"].ToString();
                    tDesc.Value = ltlDescription.Text = item["Description"].ToString();
                    ltlUnassigned.Visible = false;
                    ltlDataType.Text = "Block";
                    list_item.Attributes.Add("data-type", "Block");

                    if (pblocks.Contains(item["Name"].ToString().Trim().ToLower()))
                    {
                        edt.Visible = edt2.Visible = del.Visible = drg.Visible = false;
                    }

                    ltlNested.Text = WriteHtml(item);
                }
                else if (item["Type"].ToString() == "Code")
                {
                    hfCCID.Value = item["ID"].ToString();
                    tName.Value = ltlBlockName.Text = item["Name"].ToString();
                    tDesc.Value = ltlDescription.Text = item["Description"].ToString();
                    ltlUnassigned.Visible = true;
                    ltlDataType.Text = item["Type"].ToString();
                    ltlExtraDesc.Text = string.Format(exDesc, item["Content"].ToString(), item["ID"].ToString(), ltlDataType.Text, item["Type"].ToString(), item["Content"].ToString().Replace("\n", "<br/>"));
                    list_item.Attributes.Add("data-type", item["Type"].ToString());
                    list_item.Attributes.Add("class", "mjs-nestedSortable-no-nesting");

                    logicblock.Attributes.Add("class", "logicblock unassign");
                    hblock.Attributes.Add("class", "headblock unassignhead clearfix");
                }
                else if (item["Type"].ToString() == "Call")
                {
                    exDesc = @"<div class='loglogic clearfix inplace-edit'><p>{0}</p><div class='ico-texthold'>
				                <a href='#' class='icoedit' data-id='{1}' data-type='{2}'>edit</a></div></div>
                                <div class='loglogic clearfix inplace-cntr'><p><select class='sign-select blocks'><option selected value='{0}'>{0}</option></select>
                                </p><div class='ico-texthold'><input type='submit' class='icosave' data-id='{1}' value='Save' data-type='{2}' data-cmpnttype='{3}' data-updateType='e' />
                                <a class='in-cancel' href='#'>Cancel</a></div></div>";

                    hfCCID.Value = item["ID"].ToString();
                    tName.Value = ltlBlockName.Text = item["Name"].ToString();
                    tDesc.Value = ltlDescription.Text = item["Description"].ToString();
                    ltlUnassigned.Visible = true;
                    ltlDataType.Text = item["Type"].ToString();
                    ltlExtraDesc.Text = string.Format(exDesc, item["Content"].ToString(), item["ID"].ToString(), ltlDataType.Text, item["Type"].ToString());
                    list_item.Attributes.Add("data-type", item["Type"].ToString());
                    list_item.Attributes.Add("class", "mjs-nestedSortable-no-nesting");

                    logicblock.Attributes.Add("class", "logicblock unassign");
                    hblock.Attributes.Add("class", "headblock unassignhead clearfix");
                }
            }
        }
        /// <summary>
        /// Parses Block/Call/Other types to constant number, as string
        /// </summary>
        /// <param name="type">string:Block/Call/Other String</param>
        /// <returns>1 for Block, 2 for Call, 3 otherwise</returns>
        private string Parse_cmpnttype(string type)
        {
            if (type.Equals("Block"))
            {
                return "1";
            }
            else if (type.Equals("Call"))
            {
                return "2";
            }
            else
            {
                return "3";
            }
        }

        // Writes HTML for the nested list of container components i.e. block, code, call
        // Creates hierarchy according to the order saved into db
        private string WriteHtml(DataRowView cmpnt)
        {
            var ol = new HtmlGenericControl("ol");
            ol.Controls.Add(new HtmlGenericControl());
            using (var stringWriter = new StringWriter())
            {
                using (var writer = new HtmlTextWriter(stringWriter))
                {
                    SqlCommand command = new SqlCommand();
                    command.CommandText = "SELECT * FROM BlockElements WHERE ParentID=@ParentID ORDER BY Place ASC";
                    command.Parameters.Add(new SqlParameter("@ParentID", cmpnt["ID"].ToString()));
                    DataTable dt = BEELab.Data.DBHelper.ExecuteQuery(command);
                    DataView dv = dt.DefaultView;

                    writer.AddAttribute(HtmlTextWriterAttribute.Class, "loglogic clearfix");
                    /*if (bool.Parse(cmpnt["isVisible"].ToString()))
                    {
                        writer.AddStyleAttribute("display", "block");
                    }
                    else
                    {
                        writer.AddStyleAttribute("display", "none");
                    }*/
                    
                    writer.RenderBeginTag(HtmlTextWriterTag.Ol);

                    var name = "";
                    var isNotBlock = true;
                    var extraDesc = "";
                    var description = "";
                    var dataType = "";
                    //var unassigned = false;
                    var nestedBlock = "";
                    foreach (DataRowView item in dv)
                    {
                        isNotBlock = true;
                        nestedBlock = "";
                        if (item["Type"].ToString() == "Block")
                        {
                            name = item["Name"].ToString();
                            description = item["Description"].ToString();
                            //unassigned = false;
                            dataType = item["Type"].ToString();
                            isNotBlock = false;

                            nestedBlock = WriteHtml(item);
                        }
                        else if (item["Type"].ToString() == "Code")
                        {
                            name = item["Name"].ToString();
                            description = item["Description"].ToString();
                            extraDesc = item["Content"].ToString();
                            //unassigned = true;
                            dataType = item["Type"].ToString();
                        }
                        else if (item["Type"].ToString() == "Call")
                        {
                            name = item["Name"].ToString();
                            extraDesc = item["Content"].ToString();
                            description = item["Description"].ToString();
                            //unassigned = true;
                            dataType = item["Type"].ToString();
                        }

                        if (isNotBlock)
                        {
                            writer.AddAttribute(HtmlTextWriterAttribute.Class, "mjs-nestedSortable-no-nesting");
                        }
                        writer.AddAttribute("data-id", "list_" + item["ID"].ToString());
                        writer.AddAttribute("data-type", dataType);
                        writer.RenderBeginTag(HtmlTextWriterTag.Li);

                        writer.AddAttribute(HtmlTextWriterAttribute.Class, "logicblock");
                        writer.RenderBeginTag(HtmlTextWriterTag.Div);

                        writer.AddAttribute("data-type", dataType);
                        writer.AddAttribute(HtmlTextWriterAttribute.Class, "headblock clearfix");
                        writer.RenderBeginTag(HtmlTextWriterTag.Div);

                        writer.AddAttribute(HtmlTextWriterAttribute.Class, "headlinehold");
                        writer.RenderBeginTag(HtmlTextWriterTag.Div);

                        writer.AddAttribute(HtmlTextWriterAttribute.Class, "text");
                        writer.RenderBeginTag(HtmlTextWriterTag.Div);

                        writer.RenderBeginTag(HtmlTextWriterTag.H2);
                        writer.Write(name);

                        writer.RenderBeginTag(HtmlTextWriterTag.Span);

                        writer.Write("(" + dataType + ")");

                        writer.RenderEndTag(); // span
                        writer.RenderEndTag(); // h2

                        writer.Write("<p class='inplace-cntr'><input type='text' class='in-textbox' value='" + name + "' /></p>");

                        writer.AddAttribute(HtmlTextWriterAttribute.Href, "#");
                        writer.AddAttribute(HtmlTextWriterAttribute.Class, "icoedit");
                        writer.AddAttribute("data-id", item["ID"].ToString());
                        writer.AddAttribute("data-type", dataType);
                        writer.RenderBeginTag(HtmlTextWriterTag.A);

                        writer.Write("edit");

                        writer.RenderEndTag(); // a

                        writer.AddAttribute(HtmlTextWriterAttribute.Class, "in-save");
                        writer.RenderBeginTag(HtmlTextWriterTag.P);
                        writer.Write("<input type='submit' class='icosave' value='Save' data-id='"
                            + item["ID"].ToString() + "' data-type='" + dataType + "' data-cmpnttype='"
                            + Parse_cmpnttype(item["Type"].ToString()) + "' data-updateType='n' /><a class='in-cancel' href='#'>Cancel</a>");
                        writer.RenderEndTag(); // p

                        writer.RenderEndTag(); // div

                        writer.AddAttribute(HtmlTextWriterAttribute.Class, "text");
                        writer.RenderBeginTag(HtmlTextWriterTag.Div);

                        writer.RenderBeginTag(HtmlTextWriterTag.H4);

                        writer.Write(description);

                        writer.RenderEndTag(); // h4

                        writer.Write("<p class='inplace-cntr'><input type='text' class='in-textbox' value='" + description + "' /></p>");

                        writer.AddAttribute(HtmlTextWriterAttribute.Href, "#");
                        writer.AddAttribute(HtmlTextWriterAttribute.Class, "icoedit");
                        writer.AddAttribute("data-id", item["ID"].ToString());
                        writer.AddAttribute("data-type", dataType);
                        writer.RenderBeginTag(HtmlTextWriterTag.A);

                        writer.Write("edit");

                        writer.RenderEndTag(); // a

                        writer.AddAttribute(HtmlTextWriterAttribute.Class, "in-save");
                        writer.RenderBeginTag(HtmlTextWriterTag.P);
                        writer.Write("<input type='submit' class='icosave' value='Save' data-id='"
                            + item["ID"].ToString() + "' data-type='" + dataType + "' data-cmpnttype='"
                            + Parse_cmpnttype(item["Type"].ToString()) + "' data-updateType='d' /><a class='in-cancel' href='#'>Cancel</a>");
                        writer.RenderEndTag(); // p

                        writer.RenderEndTag(); // div
                        writer.RenderEndTag(); // div

                        writer.AddAttribute(HtmlTextWriterAttribute.Class, "icon-hold");
                        writer.RenderBeginTag(HtmlTextWriterTag.Div);

                        writer.RenderBeginTag(HtmlTextWriterTag.Span);
                        writer.AddAttribute(HtmlTextWriterAttribute.Href, "#");
                        writer.AddAttribute(HtmlTextWriterAttribute.Class, "delete");
                        writer.AddAttribute("data-cmpnttype", Parse_cmpnttype(item["Type"].ToString()));
                        writer.AddAttribute("data-cmpntid", item["ID"].ToString());
                        writer.AddAttribute("data-ccid", item["ID"].ToString());
                        writer.RenderBeginTag(HtmlTextWriterTag.A);

                        writer.Write("delete");

                        writer.RenderEndTag(); // a
                        writer.RenderEndTag(); // span

                        writer.RenderBeginTag(HtmlTextWriterTag.Span);
                        writer.AddAttribute(HtmlTextWriterAttribute.Href, "#");
                        writer.AddAttribute(HtmlTextWriterAttribute.Class, "show");
                        writer.AddAttribute("data-ccid", item["ID"].ToString());
                        writer.RenderBeginTag(HtmlTextWriterTag.A);

                        writer.Write("show");

                        writer.RenderEndTag(); // a
                        writer.RenderEndTag(); // span

                        writer.RenderBeginTag(HtmlTextWriterTag.Span);
                        writer.AddAttribute(HtmlTextWriterAttribute.Href, "#");
                        writer.AddAttribute(HtmlTextWriterAttribute.Class, "drag");
                        writer.RenderBeginTag(HtmlTextWriterTag.A);

                        writer.Write("move");

                        writer.RenderEndTag(); // a
                        writer.RenderEndTag(); // span

                        writer.RenderEndTag(); // div

                        //if (unassigned)
                        //{
                        //    writer.AddAttribute(HtmlTextWriterAttribute.Class, "unassigned");
                        //    writer.RenderBeginTag(HtmlTextWriterTag.H5);

                        //    writer.Write("unassigned");

                        //    writer.RenderEndTag(); // h5
                        //}

                        writer.RenderEndTag(); // div

                        if (isNotBlock)
                        {
                            writer.AddAttribute(HtmlTextWriterAttribute.Class, "loglogic clearfix inplace-edit");
                            writer.RenderBeginTag(HtmlTextWriterTag.Div);

                            writer.RenderBeginTag(HtmlTextWriterTag.P);
                            writer.Write(extraDesc.Replace("\n", "<br/>"));
                            writer.RenderEndTag(); // p

                            writer.AddAttribute(HtmlTextWriterAttribute.Class, "ico-texthold");
                            writer.RenderBeginTag(HtmlTextWriterTag.Div);

                            writer.AddAttribute(HtmlTextWriterAttribute.Href, "#");
                            writer.AddAttribute(HtmlTextWriterAttribute.Class, "icoedit");
                            writer.AddAttribute("data-id", item["ID"].ToString());
                            writer.AddAttribute("data-type", dataType);
                            writer.RenderBeginTag(HtmlTextWriterTag.A);

                            writer.Write("edit");

                            writer.RenderEndTag(); // a

                            writer.RenderEndTag(); // div
                            writer.RenderEndTag(); // div

                            if (item["Type"].ToString().Equals("Call"))
                            {
                                writer.Write("<div class='loglogic clearfix inplace-cntr'><p><select class='sign-select blocks'><option selected value='" +
                                    extraDesc + "'>" + extraDesc + "</select></p><div class='ico-texthold'><input type='submit' class='icosave' data-id='"
                                    + item["ID"].ToString() + "' value='Save' data-type='" + dataType + "' data-cmpnttype='"
                                    + Parse_cmpnttype(item["Type"].ToString()) + "' data-updateType='e' /><a class='in-cancel' href='#'>Cancel</a></div></div>");
                            }
                            else
                            {
                                writer.Write("<div class='loglogic clearfix inplace-cntr'><p><textarea class='in-textarea'>" +
                                    extraDesc + "</textarea></p><div class='ico-texthold'><input type='submit' class='icosave' data-id='"
                                    + item["ID"].ToString() + "' value='Save' data-type='" + dataType + "' data-cmpnttype='"
                                    + Parse_cmpnttype(item["Type"].ToString()) + "' data-updateType='e' /><a class='in-cancel' href='#'>Cancel</a></div></div>");
                            }
                        }

                        writer.RenderEndTag(); // div

                        writer.Write(nestedBlock);

                        writer.RenderEndTag(); // li
                    }
                    writer.RenderEndTag(); // ol
                }
                return stringWriter.ToString();
            }
        }

        /// <summary>
        /// Creates new Call to current stage, insert it to DB
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Button2_Click(object sender, EventArgs e)
        {
            BEELab.Logic.ProgramManagement.StageManagement.BlockElements.CreateElement("Call", int.Parse(Request.QueryString["ID"].ToString()), 0, 0, NewCallName.Text, NewCallDescription.Text, SelectedCallText, true);
            NewCallName.Text = "";
            NewCallDescription.Text = "";
            NewCallContent.ClearSelection();
            SelectedCallText = "";

            FillLogicLayer();
        }

        /// <summary>
        /// Ocuures when pressing "Back" button inside a stege. 
        /// If this stage belongs to a function - redirect to relevant FunctionManagment page
        /// If this stage belongs to a Eeperiment - redirect to relevant EditExperiment page
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Back_Click(object sender, EventArgs e)
        {
            SqlCommand command = new SqlCommand();
            command.CommandText = "SELECT * FROM Stages INNER JOIN Programs ON Stages.ProgramID = Programs.ID WHERE Stages.ID=@StageID";
            command.Parameters.Add(new SqlParameter("@StageID", int.Parse(Request.QueryString["ID"].ToString())));
            DataTable dt = BEELab.Data.DBHelper.ExecuteQuery(command);
            if (dt != null)
            {
                String type = dt.Rows[0]["Type"].ToString();
                if (type.Equals("Function"))
                    Response.Redirect("FunctionManagement.aspx");
                else
                {
                    String ProgramID = dt.Rows[0]["ProgramID"].ToString();
                    Response.Redirect("EditExperiment.aspx?ID=" + ProgramID);
                }
            }
        }

        /// <summary>
        /// Creates new Code to current stage, insert it to DB
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Submit_Click(object sender, EventArgs e)
        {
            BEELab.Logic.ProgramManagement.StageManagement.BlockElements.CreateElement("Code", int.Parse(Request.QueryString["ID"].ToString()), 0, 0, NewCodeName.Text, NewCodeDescription.Text, NewCodeContent.Text, true);
            NewCodeName.Text = "";
            NewCodeDescription.Text = "";
            NewCodeContent.Text = "";

            FillLogicLayer();
        }

        /// <summary>
        /// Handling an adding of a new block to the stage.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Button1_Click(object sender, EventArgs e)
        {
            int id = BEELab.Logic.ProgramManagement.StageManagement.BlockElements.CreateElement("Block", int.Parse(Request.QueryString["ID"].ToString()), 0, 0, NewBlockName.Text, NewBlockDescription.Text, "", true);
            NewBlockName.Text = "";
            NewBlockDescription.Text = "";

            if (AddCodeCheckBox.Checked == true)
            {
                BEELab.Logic.ProgramManagement.StageManagement.BlockElements.CreateElement("Code", int.Parse(Request.QueryString["ID"].ToString()), id, 1, "Code Element", "Default code element", "", true);
                AddCodeCheckBox.Checked = false;
            }

            FillLogicLayer();
            PopulateBlocksLiteral();
            SetBlockNamesValidation();

        }

        /// <summary>
        /// Occures when deleting a function that belongs to current stage.
        /// Function will be deleted from DB an GUI will be updated.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e)
        {
            BEELab.Logic.ProgramManagement.StageManagement.ContainerManagement.DeleteContainer(Convert.ToInt32(GridView1.DataKeys[e.RowIndex].Value));
            SetInstanceNameValidation();

            gvVariable.DataBind();

            FillLogicLayer();
        }

        /// <summary>
        /// Occuers once the user press "Submit" button - Updates stage name and description on DB
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void btnSubmit_Click(object sender, EventArgs e)
        {
            txtName.Text = txtName.Text.Replace("'", "").Replace("\"", "");
            BEELab.Logic.ProgramManagement.StageManagement.StageManagement.UpdateStage(int.Parse(Request.QueryString["ID"].ToString()), txtName.Text, txtDescription.Text);
            SetStageNameValidation();

            ScriptManager.RegisterStartupScript(this, this.GetType(), "LoadTinyMCE", "LoadTinyMCE();", true);
        }

        /// <summary>
        /// Occures when user click "Submit" in order to add new data element.
        /// Insert new DataElement into DB and updates GUI.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Button3_Click(object sender, EventArgs e)
        {
            BEELab.Logic.ProgramManagement.StageManagement.DataElements.CreateElement(int.Parse(Request.QueryString["ID"].ToString()), txtLabel.Text, int.Parse(ddlVariable.SelectedValue));
            txtLabel.Text = "";
            ddlVariable.ClearSelection();
            gvDataLayer.DataBind();
            SetDataLabelsValidation();
        }

        /// <summary>
        /// Add new function to current stage and update GUI
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void AddFunctionSubmit_Click(object sender, EventArgs e)
        {
            //Gets programd ID of current stage
            int ExperimentID = BEELab.Logic.ProgramManagement.StageManagement.StageManagement.GetProgramID(int.Parse(Request.QueryString["ID"].ToString()));

            //Add function to DB, and getting ID of the container who holds the function
            int id = Logic.ProgramManagement.StageManagement.AddRemoveFunction.AddFunction(txtIntanceName.Text, ExperimentID, int.Parse(Request.QueryString["ID"].ToString()), int.Parse(ddlFunction.SelectedValue));

            DocumentReadyLiteral.Text = "$.fancybox.open({padding : '24px', href:'FunctionSettings.aspx?ID=" + id + "&FunctionID=" + int.Parse(ddlFunction.SelectedValue) + "', type: 'iframe' });";

            //Update GUI
            ddlFunction.ClearSelection();
            txtIntanceName.Text = "";
            GridView1.DataBind();
            gvVariable.DataBind();

            FillLogicLayer();
            SetInstanceNameValidation();
            PopulateBlocksLiteral();
            HideElements();
        }

        /// <summary>
        /// Occures once user clicks on "Sumbit" in order to add new presentation layer element.
        /// Presentation layer is updated on DB and on GUI.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void btnContent_Click(object sender, EventArgs e)
        {
            BEELab.Logic.ProgramManagement.StageManagement.PresentationElements.SetContent(BEELab.Logic.ProgramManagement.StageManagement.PresentationElements.GetIDByName(int.Parse(Request.QueryString["ID"].ToString()), Properties.Settings.Default.PresentationLayer + int.Parse(Request.QueryString["ID"].ToString())), PresentationLayertxtContent.Text);

            ScriptManager.RegisterStartupScript(this, this.GetType(), "LoadTinyMCE", "LoadTinyMCE();", true);
        }

        /// <summary>
        /// Deleting an existing presentation layer element.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void GridView2_RowDeleting(object sender, GridViewDeleteEventArgs e)
        {
            ScriptManager.RegisterStartupScript(this, this.GetType(), "LoadTinyMCE", "LoadTinyMCE();", true);
        }

        /// <summary>
        /// Occures once adding new variable to the experiment. Updated DB and GUI.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Button4_Click(object sender, EventArgs e)
        {
            BEELab.Logic.ProgramManagement.VariableManagement.VariableManagement.CreateVariable(BEELab.Logic.ProgramManagement.StageManagement.StageManagement.GetProgramID(int.Parse(Request.QueryString["ID"])), TextBox3.Text, TextBox4.Text, txtDefaultValue.Text, rblScope.Text);
            TextBox3.Text = "";
            TextBox4.Text = "";
            txtDefaultValue.Text = "";
            rblScope.ClearSelection();
            gvVariable.DataBind();
            SetVarNamesValidation();

            ScriptManager.RegisterStartupScript(this, this.GetType(), "LoadTinyMCE", "LoadTinyMCE();", true);
        }

        /// <summary>
        /// Occures once deleting variable from experiments variables
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void gvVariable_RowDeleting(object sender, GridViewDeleteEventArgs e)
        {
            ScriptManager.RegisterStartupScript(this, this.GetType(), "LoadTinyMCE", "LoadTinyMCE();", true);
        }

    }
}